import React, { useCallback, useEffect, useImperativeHandle, useState } from 'react';
import { useEventTarget } from 'ahooks';
import { Dropdown, Input, Menu, message, Spin, Tree, Typography } from 'antd';
import { Key } from 'rc-tree/es/interface';

import { EllipsisOutlined, FolderOpenOutlined, PlusCircleOutlined } from '@ant-design/icons';
import GroupQuickForm from './GroupQuickForm';
import * as API from '@/services';
import { KfModal, KfTreeNode, useBackendEnum, treeUtilsInstance } from 'kf-web-library';

/**
 * 提供给外部的方法
 * actionRef
 */
export interface MaterialGroupTreeAction {
  reload: () => void;
}

export interface MaterialGroupTreeProps {
  selectedKey?: Key;
  onSelect?: (selectedKey: Key | undefined) => void;
  actionRef?: React.MutableRefObject<MaterialGroupTreeAction | undefined> | ((actionRef: MaterialGroupTreeAction) => void);
  type: string;
  readonly?: boolean;
}

const gNode: KfTreeNode = {
  key: '',
  title: <span>全部</span>,
  value: '',
  parentsId: [],
  parentsName: [],
};

type GroupModelFormType = {
  formType: 'create' | 'modify';
  bizId?: API.EntityId;
};

const EllipsisMiddle = ({ children }) => {
  const d = children.indexOf('（');
  const start = children.slice(0, d).trim();
  const suffix = children.slice(d).trim();
  return (
    <Typography.Text style={{ width: '100%' }} ellipsis={{ suffix }}>
      {start}
    </Typography.Text>
  );
};

const MaterialGroupTree: React.FC<MaterialGroupTreeProps> = (props) => {
  const { readonly = false } = props;

  const [loading, setLoading] = useState<boolean>(true);
  const [treeData, setTreeData] = useState<KfTreeNode[]>([]);
  const [datasource, setDatasource] = useState<API.MaterialGroup_TreeNode[]>([]);
  const [searchVal, { reset: searchValReset, onChange: searchValOnChange }] = useEventTarget({ initialValue: '' });
  const [treeExpandedKeys, setTreeExpandedKeys] = useState<any[]>([]);

  const { enumDict } = useBackendEnum();

  const typeName = enumDict['MaterialType'][props.type].enumDesc;

  const [groupModelFormType, setGroupModelFormType] = useState<GroupModelFormType | null>(null);

  let loadData = () => {};

  const getNodeTitle = useCallback((nodeId, nodeName, total, keyword: string | undefined = undefined) => {
    const title = `${nodeName}（${total}）`;
    return (
      <>
        <span className={'material-group-tree-node-title'}>
          <EllipsisMiddle>{title}</EllipsisMiddle>
        </span>
        {nodeId > 10 && !readonly && (
          <span className={'material-group-tree-node-tools'}>
            <Dropdown
              trigger={['click']}
              overlay={
                <Menu>
                  <Menu.Item
                    onClick={(e) => {
                      e.domEvent.preventDefault;
                      e.domEvent.stopPropagation;
                      setGroupModelFormType({ formType: 'modify', bizId: nodeId });
                    }}
                  >
                    重命名
                  </Menu.Item>
                  <Menu.Item
                    onClick={(e) => {
                      e.domEvent.preventDefault;
                      e.domEvent.stopPropagation;
                      API.deleteMaterialGroup(nodeId).then((resp) => {
                        if (resp.flag) {
                          message.info('删除分组成功');
                          loadData();
                          setTimeout(() => props.onSelect && props.onSelect(undefined), 500);
                        }
                      });
                    }}
                  >
                    删除分组
                  </Menu.Item>
                </Menu>
              }
              placement="bottomRight"
            >
              <a
                onClick={(e) => {
                  e.preventDefault();
                  e.stopPropagation();
                }}
              >
                <EllipsisOutlined />
              </a>
            </Dropdown>
          </span>
        )}
      </>
    );
  }, []);

  const highlight = (keyword = '') => {
    const expandKeys: string[] = [];
    let nodeMaterialTotal = 0;
    const nodes = treeUtilsInstance.mapNodes(datasource, (n: any, parents: any[]) => {
      const index = n.name!.indexOf(keyword);
      if (index > -1) {
        expandKeys.push(n.id.toString());
      }
      return {
        key: n.id,
        title: getNodeTitle(n.id, n.name, n.total, keyword),
        value: n.id,
        nodeName: n.name,
        parentsId: n.parentsId?.reverse(),
        parentsName: n.parentsName?.reverse(),
        switcherIcon: <FolderOpenOutlined />,
      } as KfTreeNode;
    });
    const filterNodes = !!keyword ? treeUtilsInstance.filterNodes(nodes, (node) => {
      nodeMaterialTotal += node.total;
      return node.name.indexOf(keyword) > -1;
    }): nodes;

    const dData = [
      {
        ...gNode,
        title: (
          <span>
            全部{typeName}（{nodeMaterialTotal}）
          </span>
        ),
        switcherIcon: <FolderOpenOutlined />,
        children: filterNodes,
      },
    ];
    //nodes.splice(0, 0, gNode);
    setTreeData(dData);
    setTreeExpandedKeys(expandKeys);
  };

  useEffect(() => {
    highlight(searchVal);
  }, [searchVal]);

  loadData = () => {
    setLoading(true);
    API.queryMaterialGroupTree({ types: [props.type] })
      .then((resp) => {
        if (resp.flag) {
          setDatasource(resp.data);
          const expandKeys: string[] = [];
          let nodeMaterialTotal = 0;

          const nodes = treeUtilsInstance.mapNodes( resp.data, (n: any, parents: any[]) => {
            nodeMaterialTotal += n.total;
            if (n.parentsId?.length === 0) {
              expandKeys.push(n.id.toString());
            }
            return {
              key: n.id,
              title: getNodeTitle(n.id, n.name, n.total),
              value: n.id,
              nodeName: n.name,
              parentsId: n.parentsId?.reverse(),
              parentsName: n.parentsName?.reverse(),
              switcherIcon: <FolderOpenOutlined />,
            } as KfTreeNode;
          })

          const dData = [
            {
              ...gNode,
              title: (
                <span>
                  全部{typeName}（{nodeMaterialTotal}）
                </span>
              ),
              switcherIcon: <FolderOpenOutlined />,
              children: nodes,
            },
          ];
          //nodes.splice(0, 0, gNode);
          setTreeData(dData);
          setTreeExpandedKeys(expandKeys);
        }
      })
      .finally(() => {
        setLoading(false);
      });
  };

  useEffect(() => {
    loadData();
  }, []);

  const onSelect = (selectedKeys: Key[], info: any) => {
    if (props.onSelect) {
      props.onSelect(selectedKeys.length > 0 ? selectedKeys[0] : undefined);
    }
  };

  useImperativeHandle<MaterialGroupTreeAction | undefined, MaterialGroupTreeAction>(props.actionRef, () => {
    return {
      reload: () => loadData(),
    } as MaterialGroupTreeAction;
  });

  return (
    <Spin spinning={loading}>
      <div className={'material-group-tree-title-container'}>
        <div className={'material-group-tree-title'}>{typeName}分组</div>
        <div className={'material-group-tree-title-tools'}>
          {!props.readonly && (
            <a onClick={() => setGroupModelFormType({ formType: 'create' })}>
              <PlusCircleOutlined />{' '}
            </a>
          )}
        </div>
      </div>
      <div className={'material-group-tree-search-wrap'}>
        <Input.Search style={{ marginBottom: 8 }} placeholder="分组名称" value={searchVal} onChange={searchValOnChange} allowClear />
      </div>
      <Tree.DirectoryTree
        className={'material-group-tree'}
        checkable={false}
        showIcon={false}
        //switcherIcon={<FolderOpenOutlined />}
        expandedKeys={treeExpandedKeys}
        draggable={{
          icon: false,
          nodeDraggable: (node) => {
            const { value } = node as any;
            return parseInt(value) > 10;
          },
        }}
        onDrop={(info) => {
          const { value: fromGroupId } = info.dragNode as any;
          const { value: toGroupId } = info.node as any;
          if (fromGroupId && toGroupId) {
            API.moveMaterialGroup({ fromGroupId, toGroupId, type: props.type }).then((resp) => {
              if (resp.flag) {
                loadData();
              }
            });
          }
        }}
        //onExpand={setTreeExpandedKeys}
        onSelect={onSelect}
        selectedKeys={props.selectedKey ? [props.selectedKey] : []}
        treeData={treeData}
        autoExpandParent
      />
      {!!groupModelFormType && (
        <KfModal
          width={400}
          open={true}
          title={`${groupModelFormType.formType == 'create' ? '添加' : '重命名'}分组`}
          onCancel={() => {
            setGroupModelFormType(null);
          }}
          onSubmitted={loadData}
        >
          <GroupQuickForm type={props.type} {...groupModelFormType} />
        </KfModal>
      )}
    </Spin>
  );
};

export default MaterialGroupTree;
